/*
 * System.h
 *
 *  Created on: 23 May 2011
 *      Author: allan
 */

#ifndef SYSTEM_H_
#define SYSTEM_H_

// C++ includes
#include <memory>
#include <vector>
using namespace std;

// FluidReact includes
#include "AqueousPhase.h"
#include "GaseousPhase.h"
#include "MineralPhase.h"
#include "Phase.h"
#include "Species.h"
#include "Reaction.h"

class System 
{
public:
	System();
	
	System(const System& copy);
	
	virtual ~System();
	
	void AddPhase(const AqueousPhase& aqueousPhase);
	
	void AddPhase(const GaseousPhase& gaseousPhase);
	
	void AddPhase(const MineralPhase& mineralPhase);
	
	void AddEquilibriumReaction(const EquilibriumReaction& equilibriumReaction);
	
	void AddKineticReaction(const MineralReaction& mineralReaction);
	
	void SetPrimarySpecies(const vector<string>& namesOfPrimarySpecies);
	
	void SetEquilibriumSpecies(const vector<string>& namesOfEquilibriumSpecies);
	
	void SetKineticSpecies(const vector<string>& namesOfKineticSpecies);
	
	void SetMolesOfSpecies(unsigned iSpecies, double value);
	
	void SetMolesOfSpecies(const vector<double>& moles);
	
	void SetMolesOfPrimarySpecies(const vector<double>& moles);
	
	void SetMolesOfEquilibriumSpecies(const vector<double>& moles);
	
	void SetMolesOfKineticSpecies(const vector<double>& moles);
	
	void SetMolesOfPhase(unsigned iPhase, const vector<double>& moles);
	
	void SetTemperature(double T);
	
	void SetPressure(double P);
	
	const unsigned GetNumOfSpecies() const;
	
	const unsigned GetNumOfPrimarySpecies() const;
	
	const unsigned GetNumOfEquilibriumSpecies() const;
	
	const unsigned GetNumOfKineticSpecies() const;
	
	const unsigned GetNumOfPhases() const;
	
	const unsigned GetIndexOfSpecies(string nameOfSpecies) const;
	
	const unsigned GetIndexOfPhase(string nameOfPhase) const;
	
	const unsigned GetIndexOfPrimarySpecies(unsigned iPrimary) const;
	
	const unsigned GetIndexOfEquilibriumSpecies(unsigned iEquilibrium) const;
	
	const unsigned GetIndexOfKineticSpecies(unsigned iKinetic) const;
	
	const Species& GetSpecies(unsigned iSpecies) const;
	
	const Phase* GetPhase(unsigned iPhase) const;
	
	const AqueousPhase* GetAqueousPhase() const;
	
	const GaseousPhase* GetGaseousPhase() const;
	
	const MineralPhase* GetMineralPhase(unsigned iMineralPhase) const;
	
	const EquilibriumReaction& GetEquilibriumReaction(unsigned iEquilibrium) const;
	
	const KineticReaction& GetKineticReaction(unsigned iKinetic) const;
	
	const double GetMolesOfSpecies(unsigned iSpecies) const;
	
	const double GetMolarFractionOfSpecies(unsigned iSpecies) const;
	
	const double GetActivityOfSpecies(unsigned iSpecies) const;
	
	const double GetEquilibriumReactionQuotient(unsigned iEquilibrium) const;
	
	const double GetKineticReactionQuotient(unsigned iKinetic) const;
	
	const double GetTemperature() const;
	
	const double GetPressure() const;
	
	const vector<double> GenerationRatesOfKineticSpecies() const;
	
	const vector<double> GenerationRatesOfPrimarySpecies(const vector<double>& ratesOfKineticSpecies) const;
	
	void UpdateSystem();
	
private:
	void UpdateSpeciesWithNewPhase();
	
	void UpdateActivities();
	
	void UpdateReactionQuotients();
	
	const double EquilibriumReactionQuotient(unsigned iEquilibrium) const;
	
	const double KineticReactionQuotient(unsigned iKinetic) const;
	
private:
//	typedef std::shared_ptr<Phase>        PhasePtr;
//	typedef std::shared_ptr<AqueousPhase> AqueousPhasePtr;
//	typedef std::shared_ptr<GaseousPhase> GaseousPhasePtr;
//	typedef std::shared_ptr<MineralPhase> MineralPhasePtr;
	
private:
	vector<Phase*> phases;
	
	AqueousPhase* aqueousPhase;
	
	GaseousPhase* gaseousPhase;
	
	vector<MineralPhase*> mineralPhases;
	
	vector<Species> species;
	
	vector<unsigned> idxPrimarySpecies;
	
	vector<unsigned> idxEquilibriumSpecies;
	
	vector<unsigned> idxKineticSpecies;
	
	vector<EquilibriumReaction> equilibriumReactions;
	
	vector<KineticReaction*> kineticReactions;
	
	double T;
	
	double P;
	
	vector<vector<double>> activitiesOfPhases;
	
	vector<double> Qe;
	
	vector<double> Qk;
};

#endif /* SYSTEM_H_ */



